
#include "composite_parser.h"

using namespace std;
using namespace eg;

//==================================================================================================
//                            Specific parsers implementation
//==================================================================================================

//================================ Sequence: E = E1 E2 ... En ======================================
bool seq_parser::parse(bool gen_ast)
{

    pos_type pos = the_context->input.tellg();
    int old_size_of_stack = the_context->s.size();
    //cout << "trying parsing " << to_string() << " ..." << endl;
	
	list<parser *>::iterator i = parsers.begin();
    if ( ! (*i)->parse(gen_ast) )
        return reject(pos);
    i++;
    while ( i != parsers.end() and (*i)->parse(gen_ast) )
        i++;
    if ( i == parsers.end() )
		return true;
	else
		return reject(pos,the_context->s.size()-old_size_of_stack);
}

string seq_parser::to_string()
{
	string s;
    for (list<parser *>::iterator i = parsers.begin(); i != parsers.end(); i++)
    	if ( !(*i)->is_a_rule() )
    		s += (*i)->to_string() + ' ';
    	else
    		s += (*i)->parser_name() + ' ';
    return s;
}

parser & seq_parser::operator>>(parser & p)
{
	cout <<"seq_pars op +" << endl;
    add_parser(&p);
    return *this;
}
 
parser & seq_parser::operator|(parser & p)
{
    alt_parser * alt = new alt_parser();
    alt->add_parser(this);
    alt->add_parser(&p);
    return *alt;
}

bool seq_parser::left_recursive(parser * from)
{
	return parsers.front()->left_recursive(from);
}

//==================== Alternatives (ordered choice): E = E1 / E2 / ... / En =======================
bool alt_parser::parse( bool gen_ast)
{
	int old_size_of_stack = the_context->s.size();
    pos_type pos = the_context->input.tellg();

    //cout << "trying parsing " << to_string() << " ..." << endl;
		
    for (list<parser *>::iterator i = parsers.begin(); i != parsers.end(); i++)
    {	
        if ( (*i)->parse(gen_ast) ) 
            return true;
    }
    return reject(pos,the_context->s.size()-old_size_of_stack);
}

string alt_parser::to_string()
{
	string s;
    for (list<parser *>::iterator i = parsers.begin(); i != parsers.end(); i++) {
    	if ( i != parsers.begin() )
    		s += " / ";
		if ( !(*i)->is_a_rule() )
    		s += (*i)->to_string();
    	else
    		s += (*i)->parser_name();
    }
   	return s;
}

parser & alt_parser::operator|(parser & p)
{
    add_parser(&p);
    return *this;
}
//================================================================================================= 
bool alt_parser::left_recursive(parser * from)
{
	for (list<parser *>::iterator i = parsers.begin(); i != parsers.end(); i++)
		if ( (*i)->left_recursive(from) )
			return true;
	return false;
}

